package com.github.chirspan.xaas.uc.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.chirspan.xaas.uc.dao.UcRbacUserDao;
import com.github.chirspan.xaas.uc.dao.UcRbacUserDepartmentDao;
import com.github.chirspan.xaas.uc.dao.UcRbacUserRoleDao;
import com.github.chirspan.xaas.rbac.model.RbacUser;
import com.github.chirspan.xaas.rbac.model.RbacUserDepartment;
import com.github.chirspan.xaas.rbac.model.RbacUserRole;
import com.github.chirspan.xaas.rbac.service.impl.UserServiceImpl;
import com.github.chirspan.xaas.uc.service.IRbacUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * ************************
 * <p></p>
 * *************************
 *
 * @author chenpan
 * @date 2021/2/1 18:56
 */
@Service
@Primary
public class RbacUserServiceImpl extends UserServiceImpl implements IRbacUserService {

    @Autowired
    private UcRbacUserDao userDao;

    @Autowired
    private UcRbacUserRoleDao userRoleDao;

    @Autowired
    private UcRbacUserDepartmentDao userDepartmentDao;

    @Override
    public IPage<RbacUser> getUserAndRole(Page page, RbacUser user) {
        IPage<RbacUser> pageInfo = this.userDao.selectUserAndRole(page, user);
        if (pageInfo != null) {
            List<RbacUser> userVOList = pageInfo.getRecords();
            if (CollectionUtil.isNotEmpty(userVOList)) {
                for (RbacUser userVO : userVOList) {
                    if (StrUtil.isNotBlank(userVO.getRolesStr())) {
                        userVO.setRoles(userVO.getRolesStr().split(","));
                    }
                    if(StrUtil.isNotBlank(userVO.getDeptsStr())) {
                        userVO.setDepts(userVO.getDeptsStr().split(","));
                    }
                }
            }
        }

        return pageInfo;
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    @Override
    public void addUser(RbacUser user) {
        user.setId(IdUtil.fastSimpleUUID());
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        save(user);
        saveUserGroupAndDept(user);
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    @Override
    public void updateUser(RbacUser user) {
        // 更新用户信息
        updateNotNull(user);
        // 更新用户角色关联信息：先删除后插入
        deleteUserRole(user.getId());
        saveUserGroupAndDept(user);
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    @Override
    public void deleteUser(String userId) {
        // 删除用户角色关联信息
        deleteUserRole(userId);
        // 删除用户
        delete(userId);
    }

    private void saveUserGroupAndDept(RbacUser user) {
        if (user.getRoles() != null) {
            for (String roleId : user.getRoles()) {
                RbacUserRole userRole = new RbacUserRole();
                userRole.setUserId(user.getId());
                userRole.setRoleId(roleId);
                userRoleDao.insert(userRole);
            }
        }
        if (user.getDepts() != null) {
            for (String deptId : user.getDepts()) {
                RbacUserDepartment userDepartment = new RbacUserDepartment();
                userDepartment.setUserId(user.getId());
                userDepartment.setDeptId(deptId);
                userDepartmentDao.insert(userDepartment);
            }
        }
    }

    private void deleteUserRole(String userId) {
        LambdaQueryWrapper<RbacUserRole> userRoleQueryWrapper = Wrappers.lambdaQuery(RbacUserRole.class);
        userRoleQueryWrapper.eq(RbacUserRole::getUserId, userId);
        userRoleDao.delete(userRoleQueryWrapper);

        LambdaQueryWrapper<RbacUserDepartment> userDeptQueryWrapper = Wrappers.lambdaQuery(RbacUserDepartment.class);
        userDeptQueryWrapper.eq(RbacUserDepartment::getUserId, userId);
        userDepartmentDao.delete(userDeptQueryWrapper);
    }
}
